<!--
    参考原作者：https://www.zhihu.com/people/tao-xiao-qi-75-7
    原文地址：https://zhuanlan.zhihu.com/p/111080355
    代码仓库：https://github.com/taoqi0813/vue-cesium-scale
-->
<template>
    <div class="MeasuringScale">
        <!-- 比例尺面板 -->
        <div class="scale-container">
        <div class="scale-label">{{ distanceLabel || "out of range" }}</div>
        <div
                v-if="barWidth"
                class="scale-bar"
                :style="{ width: barWidth + 'px' }"
        ></div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "MeasuringScale",
        //import引入的组件需要注入到对象中才能使用",
        components: {},
        data() {
            //这里存放数据",
            return {
                distanceLabel: undefined,
                barWidth: undefined
            };
        },
        //监听属性 类似于data概念",
        computed: {},
        //监控data中的数据变化",
        watch: {},
        //方法集合",
        methods: {
            initListener(){
                const _this = this;
                viewer.scene.postRender.addEventListener(function() {
                    _this.cesiumScale();
                });
            },
            // 比例尺
            cesiumScale() {
                let geodesic = new Cesium.EllipsoidGeodesic();
                let distances = [
                    1,
                    2,
                    3,
                    5,
                    10,
                    20,
                    30,
                    50,
                    100,
                    200,
                    300,
                    500,
                    1000,
                    2000,
                    3000,
                    5000,
                    10000,
                    20000,
                    30000,
                    50000,
                    100000,
                    200000,
                    300000,
                    500000,
                    1000000,
                    2000000,
                    3000000,
                    5000000,
                    10000000,
                    20000000,
                    30000000,
                    50000000
                ];
                // Find the distance between two pixels at the bottom center of the screen.
                let scene = viewer.scene;
                let width = scene.canvas.clientWidth;
                let height = scene.canvas.clientHeight;
                let left = scene.camera.getPickRay(
                    new Cesium.Cartesian2((width / 2) | 0, height - 1)
                );
                let right = scene.camera.getPickRay(
                    new Cesium.Cartesian2((1 + width / 2) | 0, height - 1)
                );
                let globe = scene.globe;
                let leftPosition = globe.pick(left, scene);
                let rightPosition = globe.pick(right, scene);
                if (!Cesium.defined(leftPosition) || !Cesium.defined(rightPosition)) {
                    this.barWidth = undefined;
                    this.distanceLabel = undefined;
                    return;
                }
                let leftCartographic = globe.ellipsoid.cartesianToCartographic(
                    leftPosition
                );
                let rightCartographic = globe.ellipsoid.cartesianToCartographic(
                    rightPosition
                );
                geodesic.setEndPoints(leftCartographic, rightCartographic);
                let pixelDistance = geodesic.surfaceDistance;
                // Find the first distance that makes the scale bar less than 100 pixels.
                let maxBarWidth = 100;
                let distance;
                for (
                    let i = distances.length - 1;
                    !Cesium.defined(distance) && i >= 0;
                    --i
                ) {
                    if (distances[i] / pixelDistance < maxBarWidth) {
                        distance = distances[i];
                    }
                }
                if (Cesium.defined(distance)) {
                    var label =
                        distance >= 1000
                            ? (distance / 1000).toString() + " km"
                            : distance.toString() + " m";
                    this.barWidth = (distance / pixelDistance) | 0;
                    this.distanceLabel = label;
                } else {
                    this.barWidth = undefined;
                    this.distanceLabel = undefined;
                }
            }
        },
        //生命周期 - 创建之前",数据模型未加载,方法未加载,html模板未加载
        beforeCreate() {
        },

        //生命周期 - 创建完成（可以访问当前this实例）",数据模型已加载，方法已加载,html模板已加载,html模板未渲染
        created() {

        },
        //生命周期 - 挂载之前",html模板未渲染
        beforeMount() {

        },

        //生命周期 - 挂载完成（可以访问DOM元素）",html模板已渲染
        mounted() {
            this.initListener()
        },

        //生命周期 - 更新之前",数据模型已更新,html模板未更新
        beforeUpdate() {

        },
        //生命周期 - 更新之后",数据模型已更新,html模板已更新
        updated() {

        },
        //生命周期 - 销毁之前",
        beforeDestroy() {

        },
        destroyed() {

        },
        //生命周期 - 销毁完成",
        //如果页面有keep-alive缓存功能，这个函数会触发",
        activated() {

        },
    }

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    .scale-container {
        position: absolute;
        z-index: 1001;
        right: 0;
        bottom: 10px;
        width: 120px;
        height: 30px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        background: rgba(10, 31, 59, 0.7);
    }
    .scale-label {
        font-size: 12px;
        color: #fff;
        text-align: center;
    }
    .scale-bar {
        position: relative;
        padding-top: 10px;
    }
    .scale-bar::after {
        content: "";
        position: absolute;
        width: 100%;
        height: 10px;
        border: 1px solid #fff;
        border-top: none;
        left: 0;
        bottom: 0;
    }
</style>

